package com.yjzx.util.common.util.unmodifiable;

import com.yjzx.util.common.util.collection.EmptyUtils;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.util.*;

/**
 * @author yjzx
 * @date 2024/8/14
 * @description UnmodifiableMethodInterceptor
 */
public class UnmodifiableMethodInterceptor implements MethodInterceptor {
    private final Object o;
    /**
     * 必定执行的方法
     */
    List<Method> includeMethods;
    /**
     * 禁止执行的方法
     */
    List<Method> excludeMethods;
    /**
     * 禁止修改的字段
     */
    List<String> fieldNames;

    public UnmodifiableMethodInterceptor(Object o) {
        this.o = o;
        this.excludeMethods = Collections.emptyList();
        this.includeMethods = Collections.emptyList();
    }
    public UnmodifiableMethodInterceptor(Object o, List<Method> excludeMethods) {
        this.o = o;
        this.excludeMethods = EmptyUtils.isEmpty(excludeMethods) ? Collections.emptyList() : excludeMethods;
        this.includeMethods = Collections.emptyList();
    }
    public UnmodifiableMethodInterceptor(Object o, UnmodifiableObject unmodifiableObject) {
        this.o = o;
        if (unmodifiableObject!=null){
            Set<Method> excludeMethods = new HashSet<>(unmodifiableObject.getExcludeMethods()) ;
            List<Method> includeMethods = unmodifiableObject.getIncludeMethods();
            this.excludeMethods = EmptyUtils.isEmpty(excludeMethods) ? Collections.emptyList() : unmodifiableObject.getExcludeMethods();
            this.includeMethods = EmptyUtils.isEmpty(includeMethods) ? Collections.emptyList() : includeMethods;
        }

    }


    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        if (EmptyUtils.isNotEmpty(includeMethods)){
            if (includeMethods.contains(method)) {
                return methodProxy.invoke(this.o, objects);
            }
        }
        if (EmptyUtils.isNotEmpty(excludeMethods)){
            if (excludeMethods.contains(method)){
                throw new UnsupportedOperationException("当前对象此方法不允许访问");
            }
        }else {
            if (method.getName().startsWith("set")) {
                throw new UnsupportedOperationException("当前对象此方法不允许访问");
            }
        }

        return methodProxy.invoke(this.o, objects);
    }

}
